<?php

/*
Copyright 2009-2011 Sam Weiss
All Rights Reserved.

This file is part of Spark/Plug.

Spark/Plug is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

if (!defined('spark/plug'))
{
	header('HTTP/1.1 403 Forbidden');
	exit('<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN"><html><head><title>403 Forbidden</title></head><body><h1>Forbidden</h1><p>You don\'t have permission to access the requested resource on this server.</p></body></html>');
}

// -----------------------------------------------------------------------------

class _SparkCacher_file extends SparkCacher
{
	private $_default_timeout;
	private $_gc_probability;
	private $_name_space;
	private $_index_page;
	private $_cache_dir;
	private $_cache_dir_perms;
	private $_cache_file_perms;
	private $_cache_root;

	// --------------------------------------------------------------------------

	public function __construct($params)
	{
		parent::__construct($params);

		$this->_default_timeout = !empty($params['lifetime']) ? $params['lifetime'] : 0;
		$this->_gc_probability = !empty($params['gc_probability']) ? $params['gc_probability'] : 5;
		$this->_index_page = !empty($params['index_page']) ? trim($params['index_page'], '/') : '';
		$this->_cache_dir = !empty($params['cache_dir']) ? $params['cache_dir'] : 'cache';
		$this->_cache_dir_perms = !empty($params['dir_mode']) ? $params['dir_mode'] : 0755;
		$this->_cache_file_perms = !empty($params['file_mode']) ? $params['file_mode'] : NULL;
		if ($this->_cache_dir[0] !== '/')
		{
			$this->_cache_dir = SparkUtil::doc_root() . '/' . $this->_cache_dir;
		}
		$this->setNameSpace(@$params['namespace']);
	}

	// --------------------------------------------------------------------------

	// Public Methods

	// --------------------------------------------------------------------

	public function setDefaultTimeout($timeout)
	{
		$this->_default_timeout = !empty($timeout) ? $timeout : 0;
	}

	// --------------------------------------------------------------------

	public function setNameSpace($namespace)
	{
		$this->_name_space = empty($namespace) ? '' : $namespace;
		$this->_cache_root = $this->_cache_dir . '/' . $this->_name_space;
	}

	// --------------------------------------------------------------------------

	public function get($key)
	{
		$path = $this->keyToFile($key);
		
		if ($this->_default_timeout)
		{
			if (($modTime = @filemtime($path)) === false)
			{
				return false;
			}

			if ((time() - $modTime) >= $this->_default_timeout)
			{
				unlink($path);
				return false;
			}
		}
		
		return @file_get_contents($path);
	}

	// --------------------------------------------------------------------------

	public function set($key, $item, $timeout = NULL)
	{
		$this->keyToPathAndFile($key, $path, $file);

		if (!is_dir($path))
		{
			$saveMask = umask(0002);
			mkdir($path, $this->_cache_dir_perms, true);
			umask($saveMask);
		}

		if (file_put_contents($filename = $path.'/'.$file, $item, LOCK_EX) !== false)
		{
			if ($this->_cache_file_perms !== NULL)
			{
				return chmod($filename, $this->_cache_file_perms);
			}
			return true;
		}
		
		return false;
	}

	// --------------------------------------------------------------------------

	public function replace($key, $item, $timeout = NULL)
	{
		return $this->set($key, $item, $timeout);
	}

	// --------------------------------------------------------------------------

	public function remove($key)
	{
		return @unlink($this->keyToFile($key));
	}

	// --------------------------------------------------------------------------

	public function clear()
	{
		if (is_dir($this->_cache_root))
		{
			$iter = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($this->_cache_root), RecursiveIteratorIterator::CHILD_FIRST);
			foreach ($iter as $file)
			{
				$filePath = $file->getPathname();
				if ($file->isDir())
				{
					rmdir($filePath);
				}
				else
				{
					unlink($filePath);
				}
			}
		}
	}

	// --------------------------------------------------------------------------

	// Private Methods

	// --------------------------------------------------------------------------

	public function keyToFile($key)
	{
		$this->keyToPathAndFile($key, $path, $file);
		return $path . '/' . $file;
	}
	
	// --------------------------------------------------------------------------

	public function keyToPathAndFile($key, &$path, &$file)
	{
		$key = trim($key, '/');

		$path = $this->_cache_root;
		
		if (empty($key))
		{
			$file = 'index.html';
		}
		
		else
		{
			$pathInfo = pathinfo($key);
			$dirName = $pathInfo['dirname'];
			$fileName = $pathInfo['basename'];
			
			if ($dirName === '.')
			{
				if (!empty($this->_index_page))
				{
					$path .= '/' . $this->_index_page;
				}
				$file = ($fileName == $this->_index_page) ? 'index.html' : ($fileName . (empty($pathInfo['extension']) ? '.html' : ''));
			}
			
			else
			{
				$path .= '/' . $dirName;
				$file = $fileName . (empty($pathInfo['extension']) ? '.html' : '');
			}
		}
	}

	// --------------------------------------------------------------------------
}
